Raspberry Pi 4 Model B Rev 1.2 を Synology NAS の TFTP と NFS を使って Network boot する
いつのまにか(2020/04/16 リリースの pieeprom から)Network boot の機能が正式リリースされていてかなりめでたい。
弊宅では Raspberry Pi 4 Model B 上の OpenSSH Server のみを外部に公開する運用をしており、Pi 4 に死なれると外から LAN 内サービスに一切アクセスできなくなるという問題があって、セットアップしてみたので記録しておく。 この記事は 2020/06/27 に書いた。
目的
既にSD カードや USB デバイスを使って Raspberry Pi 4 を使っているが、SD カードの寿命によってデータが消えることが心配であり、NAS の冗長化された HDD 上にデータを記録したい
また、移行に伴なってデータが消えないようにしたい(そのまま移行したい)
Network boot の流れ(ざっくり)
Raspberry Pi の EEPROM にある Bootloader が DHCP から IP アドレスと TFTP サーバーの位置を受けとる
受けとった IP を使って Bootloader が TFTP サーバーと通信しファイルを取得する
Bootloader が取得したファイルを使って Linux Kernel を起動する
Linux kernel は cmdline として渡された root=/dev/nfs nfsroot=<IP>:<NFS directory> の指定から root をマウントする
/etc/fstab を使いさらに必要なディレクトリがマウントされ、ブートする
例示の前提
NAS が 192.168.11.1 にあること
Raspberry Pi は 192.168.11.2 という固定 IP を使っていること
サーバーのセットアップ
Synology NAS に2つの共有フォルダを作成する
Control Panel > Shared Folder から Create する
Recycle bin は不要なので切ってよいはず
この記事ではフォルダは Volume 1 というボリュームの下に作成したこととする
/ を置く共有フォルダ。NFS で公開される。この記事では nfsroot とする
/boot を置く共有フォルダ。TFTP と NFS の両方で公開される。この記事では nfsboot とする
Synology NAS で TFTP を有効にする
Control Panel > File Servers > TFTP から Enable TFTP service で有効にする
root folder は nfsboot にする
Synology NAS で NFS を有効にする
Control Panel > File Servers > SMB / AFP / NFS から Enable NFS で有効にする
Synology NAS の NFS で nfsroot と nfsboot を露出させる
Control Panel > Shared Folder から各フォルダを選択し Edit 画面の NFS Permissions から Create する
この段階では IP を絞りこまないほうがよい、そのため Hostname or IP は * とする
nfsroot, nfsboot へのファイル転送を Raspberry Pi ではないマシンで行うことが予期されるということと、トラブルシューティングの際に考えなければいけない要素が増えるため
Allow connection from non-priviledged ports を有効にしておくとよい(たぶん)
いらないかもしれない
こうなる
https://gyazo.com/af67a2d3a5b41cbdd5220aafd26264ff
DHCP が TFTP Server の IP を配信するように設定する
民生品の適当なルータ(牛とか)ではできないと思うので自前でサーバーを建てる必要がある
(未検証)おそらく次の RFC に書かれている DHCP Option を広告させるのだと思われる
私はDebian 上に構築した ISC DHCP を使っていたので /etc/dhcp/dhcpd.conf に以下の設定を追加した
code:config
host pi {
hardware ethernet 06:00:00:00:00:00;
fixed-address 192.168.11.2;
option tftp-server-name "192.168.11.1";
}
Raspberry Pi のみに TFTP サーバーの存在を伝えるために MAC Address を使っている
MAC Address は Raspberry Pi 上で ip link を実行して取得しておく
また、固定 IP にするためにその設定も含む
「TFTP で読み込むべきファイル名を DHCP で指定しなければいけないのではないのか?」と思うかもしれない。何も指定しなくても Raspberry Pi 4 のブートローダーが勝手に TFTP サーバー直下を /boot のように扱うため、必要ないだけである
ソースコードを見たわけではなく、各種参考文献にファイル名の記述がなかったこと、起動に成功したあとの TFTP サーバーへのアクセスログから判断しただけではあるので、もしかしたら不正確かもしれない
そもそも指定しても尊重してくれるのかすらわからない。たくさんのファイルを読み込むので、どこからどこまでが決め打ちなのかがわからない
Raspberry Pi 4 のセットアップと Raspberry Pi OS の NFS への転送
Bootloader を Network boot できるように設定する
これは Linux からしか設定できないので、既にある起動デバイス (SD など) から起動して設定する
BOOT_ORDER のどこかに 0x2 を足す
nibble (16進数表記したときの1桁, 4 bit) 毎にブートオプションを表わし 32bit なので 8個 までブートオプションが書ける
私は緊急時 SD カードや USB mass storage からも起動できるように 0xf241 にした
0x1 (SD) -> 0x4 (USB mass storage) -> 0x2 (Network) -> 0xf (Restart) で実行される
もともと 0xf41 だった
0xf が失敗扱いで再起動して再試行なのでその前に実行されるようにだけ気をつけた
起動デバイスを取り外す
これは先述の通り BOOT_ORDER に Network boot より先に SD, USB mass storage が起動するように設定しているので、外さないと Network boot が始まらないため
/ と /boot をそれぞれ Synology NAS の NFS に転送する
Unix-like な環境を使って転送するならば……
1. Pi から起動デバイスを取り外して、転送を実行するマシンに接続する
2. 起動デバイスのパーティションとNFS ディレクトリを mount して rsync -xa で転送するとよい
NFS は mount -t nfs でマウントする
共有ファルダを指すパスは Synology NAS の共有フォルダ設定に表示されているので参考にするとよい
https://gyazo.com/b1d7b9341664ba14d87654cca65c37d0
Mount path: /volume1/example
私は Arch Linux を使っているが nfs-tools が入っておらず最初マウントできなかった
Raspberry Pi OS (旧称 Raspbian) で特に構成を弄っていなければ第一パーティションが /boot, 第二パーティションが / のはず
rsync は末尾に / がないと転送元のディレクトリを作成してくるので、どちらにも / を指定しましょう
rsync -xa ./sdboot/ ./nfsboot/
Windows の場合はがんばって。Raspberry Pi から起動デバイスを取り外さず、起動中にデータを転送してもいいのかもしれない
まともにできるのか知らんけど……
nfsboot にある cmdline.txt および nfsroot にある /etc/fstab を編集し NFS でマウントするように指定する
例
code:cmdline.txt
console=serial0,115200 console=tty1 root=/dev/nfs nfsroot=192.168.11.1:/volumes1/nfsroot,proto=tcp rw ip=dhcp elevator=deadline rootwait
code:/etc/fstab
proc /proc proc defaults 0 0
192.168.11.1:/volume1/nfsboot /boot nfs defaults,proto=tcp 0 2
192.168.11.1:/volume1/nfsroot / nfs defaults,proto=tcp 0 1
トラブルシューティング
Synology NAS の TFTP サーバーは設定 (Control Panel > File Servers > TFTP) からファイルへのアクセスログの出力ができる。有効にしておくとカーネルが読み込めているかどうかがわかりやすいので、設定するとよい
コンソールにアクセスできる手段は持っておくべき
micro HDMI ケーブル あるいは シリアル で接続できるようにしておくべき
起動に失敗しているのが通信中なのかが判断しにくいので困る
Synology NAS は NFS へのアクセスログは取れないっぽい、という事情もあり…
私はこの手段を持ちあわせていなかったので、エスパーになる必要があった
1時間から2時間くらい格闘していた
私の環境では Gbps Ethernet で NAS と Pi 4 が通信できる状態で起動するまで1分程はかかるので、気長に待たなければいけない
なにがボトルネックかは調査していないけど
NFS が細かいファイルの転送に弱いのかもしれない
幣環境では TFTP のログからしてカーネルの読み込みに 5s くらいかかっているので、そのあと rootfs を読みに行くと考えると妥当なのかもしれない
(反省)Wi-Fi to Ethernet コンバータで検証してはいけない。起動が遅すぎて失敗してるかどうか判断しにくい
当然っちゃ当然。ケーブルが邪魔でデスクまで有線 LAN 伸ばしておらず簡単に検証するために使ってしまったが、簡単とは真反対になってしまった
Raspberry Pi 2 Model B をコンバータにしていて、このお手製コンバータは大量に通信すると ping が宇宙になったり(不安定で 100ms を超えたり)するという問題があるのでそれのせいかもしれない
起動に成功したら
NFS, TFTP のアクセス元 IP を絞るとより良いかもしれない
DHCP で固定 IP を振ることが前提ではある
NFS なら作成した権限の編集画面にある
Control Panel > Shared Folder から各フォルダを選択し Edit 画面の NFS Permissions で作ったやつ
同時に複数箇所からもマウントできるので絞っておくのが無難だと思う
TFTP なら有効にした際に開いた設定ページの Advanced Settings の下に IP address range という設定がある
Control Panel > File Servers > TFTP
デフォルト Read-only だし、アクセスされても被害は少ないので、宅内なら気にしなくてもいいかもしれないが
参考文献
Linux のサーバーに NFS, DHCP (dhcpcd), TFTP (dhcpcd) をセットアップしそこからブートさせるもの
全体の流れがまとまっており、一番参考になった
これ見ればいいと思う
Synology NAS の操作の参考に
3.1 Setting up PXE with TFTP service on Synology NAS and an external DHCP server が参考になる
Bootloader の設定変更の参考に
Linux kernel document。NFS マウントのオプションを知るために見た
Raspberry Pi 4 ではなく 3 までだが、NFS にどういうファイルを置くのか参考になるかと思って見た
サーバーのことを書いてるのかクライアントのことを書いてるのかわかりにくいので、あまりオススメしない
(英語が読めないないだけかも?)
特に NFS 関連のソフトウエアをあらかじめインストールしないといけないのかと思ってしまう
ところで
TFTP のアクセスログを見るとなぜか bootcode.bin にアクセスが来ているがなんでなんだろう?